// ProcessHandle.cpp: implementation of the CProcessHandle class.
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "data.h"


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CProcessHandle::CProcessHandle(HWND hWndParent)
{
	for (int rii = 0; rii < MAX_SUPPORT_PROCESS; rii++)
	{
		memset(&(m_ppsInfo[rii]), 0, sizeof (PROCESS_STATUS));
		m_ppsInfo[rii].m_Process_Information.hThread = NULL;
		m_ppsInfo[rii].m_Process_Information.hProcess = NULL;
	}
	m_hWndHost = hWndParent;
	InitializeCriticalSection(&csNewProcess);
}

CProcessHandle::~CProcessHandle()
{
	for (int rii = 0; rii < MAX_SUPPORT_PROCESS; rii++)
	{
		DeleteProcessByIndex(rii);
	}
	DeleteCriticalSection(&csNewProcess);
}

LONG CProcessHandle::InsertProcess(LONG lProcessID, LPCTSTR lpctProcessName, LPCTSTR lpctCommandLine)
{
	for (int rii = 0; rii < MAX_SUPPORT_PROCESS; rii++)
	{
		if (m_ppsInfo[rii].m_lProcessID == 0)
		{
			if (wcslen(lpctProcessName) != 0)
			{
				m_ppsInfo[rii].m_lptProcessName = new WCHAR[wcslen(lpctProcessName) + 1];
				wcscpy(m_ppsInfo[rii].m_lptProcessName, lpctProcessName);
			}
			
			if (wcslen(lpctCommandLine) != 0)
			{
				m_ppsInfo[rii].m_lptCommandLine = new WCHAR[wcslen(lpctCommandLine) + 1];
				wcscpy(m_ppsInfo[rii].m_lptCommandLine, lpctCommandLine);
			}

			m_ppsInfo[rii].m_lProcessID = lProcessID;
			return rii;
		}
	}

	return -1L;
}

LONG CProcessHandle::DeleteProcessByIndex(LONG lIndex)
{
	DWORD	dwExitCode;
	if (lIndex >= MAX_SUPPORT_PROCESS)
	{
		return -1L;
	}

	m_ppsInfo[lIndex].m_lProcessID = 0;
	if (m_ppsInfo[lIndex].m_lptProcessName != NULL)
	{
		delete [] m_ppsInfo[lIndex].m_lptProcessName;
	}
	
	if (m_ppsInfo[lIndex].m_lptCommandLine != NULL)
	{
		delete [] m_ppsInfo[lIndex].m_lptCommandLine;
	}

	if (m_ppsInfo[lIndex].m_Process_Information.hProcess != NULL)
	{
		if (GetExitCodeProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
			&dwExitCode))
		{
			if (dwExitCode == STILL_ACTIVE) 
			{
				TerminateProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,-1);
			}
		}
		CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hProcess);
		m_ppsInfo[lIndex].m_Process_Information.hProcess = NULL;
	}

	if (m_ppsInfo[lIndex].m_Process_Information.hThread != NULL)
	{
/*		if (GetExitCodeThread(m_ppsInfo[lIndex].m_Process_Information.hThread,
			&dwExitCode))
		{
			if (dwExitCode == STILL_ACTIVE) 
			{
				TerminateThread(m_ppsInfo[lIndex].m_Process_Information.hThread,-1);
			}
		}
*/
		CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hThread);
		m_ppsInfo[lIndex].m_Process_Information.hThread = NULL;
	}	

	return 0L;
}

LONG CProcessHandle::DeleteOneProcess(LONG lProcessID)
{
	DWORD	dwExitCode;
	if (lProcessID == 0)
	{
		return -1L;
	}

	for (int lIndex = 0; lIndex < MAX_SUPPORT_PROCESS; lIndex++)
	{

		if (m_ppsInfo[lIndex].m_lProcessID != lProcessID)
		{
			continue;
		}
		m_ppsInfo[lIndex].m_lProcessID = 0;
		if (m_ppsInfo[lIndex].m_lptProcessName != NULL)
		{
			delete [] m_ppsInfo[lIndex].m_lptProcessName;
		}
		
		if (m_ppsInfo[lIndex].m_lptCommandLine != NULL)
		{
			delete [] m_ppsInfo[lIndex].m_lptCommandLine;
		}

		if (m_ppsInfo[lIndex].m_Process_Information.hProcess != NULL)
		{
			if (GetExitCodeProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
				&dwExitCode))
			{
				if (dwExitCode == STILL_ACTIVE) 
				{
					TerminateProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,-1);
				}
			}
			CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hProcess);
			m_ppsInfo[lIndex].m_Process_Information.hProcess = NULL;
		}

		if (m_ppsInfo[lIndex].m_Process_Information.hThread != NULL)
		{
/*			if (GetExitCodeThread(m_ppsInfo[lIndex].m_Process_Information.hThread,
				&dwExitCode))
			{
				if (dwExitCode == STILL_ACTIVE) 
				{
					TerminateThread(m_ppsInfo[lIndex].m_Process_Information.hThread,-1);
				}
			}*/
			CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hThread);
			m_ppsInfo[lIndex].m_Process_Information.hThread = NULL;
		}	
		return 0L;
	}

	return -1L;
}

LONG CProcessHandle::SetProcessWindowHandle(LONG lProcessID, HWND hWnd)
{
	if (lProcessID == 0)
	{
		return -1L;
	}
	for (int lIndex = 0; lIndex < MAX_SUPPORT_PROCESS; lIndex++)
	{

		if (m_ppsInfo[lIndex].m_lProcessID != lProcessID)
		{
			continue;
		}

		m_ppsInfo[lIndex].m_hwCommunicationWindow = hWnd;
		return 0L;
	}

	return -1L;
}


LONG CProcessHandle::SendWindowMessage(LONG lProcessID,UINT message, WPARAM wParam, LPARAM lParam)
{
	DWORD dwExitCode = 0;
	if (lProcessID == 0)
	{
		return -1L;
	}
	for (int lIndex = 0; lIndex < MAX_SUPPORT_PROCESS; lIndex++)
	{

		if (m_ppsInfo[lIndex].m_lProcessID != lProcessID)
		{
			continue;
		}
		if (m_ppsInfo[lIndex].m_Process_Information.hProcess == NULL)
		{
			return -1L;
		}
		if (!GetExitCodeProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
				&dwExitCode))
		{
			return -2L;
		}
		if (dwExitCode != STILL_ACTIVE)
		{
			return -3L;
		}
		if (m_ppsInfo[lIndex].m_hwCommunicationWindow == NULL)
		{
			return -4L;
		}
//		if (WM_COPYDATA == message)
//		{
//			wParam = (WPARAM)m_hWndHost;
//		}
		return SendMessage(m_ppsInfo[lIndex].m_hwCommunicationWindow,message,
			wParam,lParam);

	}

	return -5L;
}
LONG CProcessHandle::PostWindowMessage(LONG lProcessID,UINT message, WPARAM wParam, LPARAM lParam)
{
	DWORD dwExitCode = 0;
	if (lProcessID == 0)
	{
		return -1L;
	}

	for (int lIndex = 0; lIndex < MAX_SUPPORT_PROCESS; lIndex++)
	{

		if (m_ppsInfo[lIndex].m_lProcessID != lProcessID)
		{
			continue;
		}
		if (m_ppsInfo[lIndex].m_Process_Information.hProcess == NULL)
		{
			return -1L;
		}
		if (!GetExitCodeProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
				&dwExitCode))
		{
			return -2L;
		}
		if (dwExitCode != STILL_ACTIVE)
		{
			return -3L;
		}
		if (m_ppsInfo[lIndex].m_hwCommunicationWindow == NULL)
		{
			return -4L;
		}
		
		return PostMessage(m_ppsInfo[lIndex].m_hwCommunicationWindow,message,
			wParam,lParam);
	}

	return -5L;
}
LONG CProcessHandle::PostThreadMessage(LONG lProcessID,UINT message, WPARAM wParam, LPARAM lParam)
{
	DWORD dwExitCode = 0;
	if (lProcessID == 0)
	{
		return -1L;
	}
	
	for (int lIndex = 0; lIndex < MAX_SUPPORT_PROCESS; lIndex++)
	{		
		if (m_ppsInfo[lIndex].m_lProcessID != lProcessID)
		{
			continue;
		}

		if (m_ppsInfo[lIndex].m_Process_Information.hProcess == NULL)
		{
			return -1L;
		}

		if (!GetExitCodeProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
				&dwExitCode))
		{
			return -2L;
		}

		if (dwExitCode != STILL_ACTIVE)
		{
			return -3L;
		}

		return ::PostThreadMessage(
			m_ppsInfo[lIndex].m_Process_Information.dwThreadId,
			message,wParam,lParam);
	}

	return -5L;
}

LONG CProcessHandle::BroadcastWindowMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
	DWORD dwExitCode = 0;

	for (int lIndex = 0; lIndex < MAX_SUPPORT_PROCESS; lIndex++)
	{

		if (m_ppsInfo[lIndex].m_lProcessID == 0)
		{
			continue;
		}
		if (m_ppsInfo[lIndex].m_Process_Information.hProcess == NULL)
		{
			continue;
		}
		if (!GetExitCodeProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
				&dwExitCode))
		{
			continue;
		}
		if (dwExitCode != STILL_ACTIVE)
		{
			continue;
		}
		if (m_ppsInfo[lIndex].m_hwCommunicationWindow == NULL)
		{
			continue;
		}
		PostMessage(m_ppsInfo[lIndex].m_hwCommunicationWindow,message,
			wParam,lParam);
	}

	return 0L;
}

LONG CProcessHandle::RunOneProcess(LONG lProcessID)
{
	DWORD dwExitCode;
	EnterCriticalSection(&csNewProcess);
	if (lProcessID == 0)
	{
		LeaveCriticalSection(&csNewProcess);
		return -1L;
	}
	
	for (int lIndex = 0; lIndex < MAX_SUPPORT_PROCESS; lIndex++)
	{

		if (m_ppsInfo[lIndex].m_lProcessID != lProcessID)
		{
			continue;
		}
		
		if (m_ppsInfo[lIndex].m_Process_Information.hProcess != NULL)
		{	
			
			if (GetExitCodeProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
				&dwExitCode))
			{
				
				if (dwExitCode == STILL_ACTIVE)
				{
					ShowWindow(m_ppsInfo[lIndex].m_hwCommunicationWindow,SW_SHOW);
					::SetWindowPos(m_ppsInfo[lIndex].m_hwCommunicationWindow,
						HWND_TOPMOST,0,0,0,0,SWP_NOSIZE);
					LeaveCriticalSection(&csNewProcess);
					return 0L;
				}
			}
			CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hProcess);
			m_ppsInfo[lIndex].m_Process_Information.hProcess = NULL;
			CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hThread);
			m_ppsInfo[lIndex].m_Process_Information.hThread = NULL;
		}

//		MessageBox(NULL,L"RunProcess",NULL,MB_OK);
		if (!CreateProcess(m_ppsInfo[lIndex].m_lptProcessName,
			m_ppsInfo[lIndex].m_lptCommandLine,NULL,NULL,
			NULL,CREATE_SUSPENDED,NULL,NULL,NULL,
			&(m_ppsInfo[lIndex].m_Process_Information)))
		{
			//return NULL;
			if (m_ppsInfo[lIndex].m_Process_Information.hProcess != NULL)
			{
				CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hProcess);
				m_ppsInfo[lIndex].m_Process_Information.hProcess = NULL;
			}
			if (m_ppsInfo[lIndex].m_Process_Information.hThread != NULL)
			{
				CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hThread);
				m_ppsInfo[lIndex].m_Process_Information.hThread = NULL;
			}
			m_ppsInfo[lIndex].m_Process_Information.dwThreadId = 0;
			m_ppsInfo[lIndex].m_Process_Information.dwProcessId = 0;
		}
		else
		{
			SetThreadPriority(m_ppsInfo[lIndex].m_Process_Information.hThread,
				THREAD_PRIORITY_BELOW_NORMAL);
			if (ResumeThread(m_ppsInfo[lIndex].m_Process_Information.hThread)
				== 0xFFFFFFFF)
			{
				TerminateProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
					0x0001);
				CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hThread);
				m_ppsInfo[lIndex].m_Process_Information.hThread = NULL;
				CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hProcess);
				m_ppsInfo[lIndex].m_Process_Information.hProcess = NULL;
				m_ppsInfo[lIndex].m_Process_Information.dwThreadId = 0;
				m_ppsInfo[lIndex].m_Process_Information.dwProcessId = 0;
				LeaveCriticalSection(&csNewProcess);
				return -3L;
			}
			Sleep(100);
			::PostThreadMessage(
			m_ppsInfo[lIndex].m_Process_Information.dwThreadId,
			WM_PROTOCOLNEGOTIATEMESSAGE,(WPARAM)m_hWndHost, (LPARAM)'M');

			LeaveCriticalSection(&csNewProcess);
			return 0L;
		}
	}
	LeaveCriticalSection(&csNewProcess);
	return -5L;
}

BOOL CProcessHandle::IsAPRunning(LONG lProcessID)
{
	DWORD dwExitCode;
	if (lProcessID == 0)
	{
		return FALSE;
	}

	for (int lIndex = 0; lIndex < MAX_SUPPORT_PROCESS; lIndex++)
	{

		if (m_ppsInfo[lIndex].m_lProcessID != lProcessID)
		{
			continue;
		}
		
		if (m_ppsInfo[lIndex].m_Process_Information.hProcess != NULL)
		{	
			
			if (GetExitCodeProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
				&dwExitCode))
			{
				
				if (dwExitCode == STILL_ACTIVE)
				{
					return TRUE;
				}
			}
		}
	}
	return FALSE;
}

HWND CProcessHandle::GetHostWindowHandle()
{
	return m_hWndHost;
}

LONG CProcessHandle::SetHostWindowHandle(HWND hWnd)
{
	m_hWndHost = hWnd;
	return 0L;
}

LONG CProcessHandle::KillOneProcess(LONG lProcessID)
{
	DWORD	dwExitCode;
	if (lProcessID == 0)
	{
		return -1L;
	}

	for (int lIndex = 0; lIndex < MAX_SUPPORT_PROCESS; lIndex++)
	{

		if (m_ppsInfo[lIndex].m_lProcessID != lProcessID)
		{
			continue;
		}
		if (m_ppsInfo[lIndex].m_Process_Information.hProcess != NULL)
		{
			if (GetExitCodeProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
				&dwExitCode))
			{
				if (dwExitCode == STILL_ACTIVE) 
				{
					TerminateProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,-1);
				}
			}
			CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hProcess);
			m_ppsInfo[lIndex].m_Process_Information.hProcess = NULL;
		}

		if (m_ppsInfo[lIndex].m_Process_Information.hThread != NULL)
		{
/*			if (GetExitCodeThread(m_ppsInfo[lIndex].m_Process_Information.hThread,
				&dwExitCode))
			{
				if (dwExitCode == STILL_ACTIVE) 
				{
					TerminateThread(m_ppsInfo[lIndex].m_Process_Information.hThread,-1);
				}
			}*/
			CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hThread);
			m_ppsInfo[lIndex].m_Process_Information.hThread = NULL;
		}	
		return 0L;
	}

	return -1L;
}

LONG CProcessHandle::KillOneProcessByIndex(LONG lIndex)
{
	DWORD	dwExitCode;
	if (lIndex >= MAX_SUPPORT_PROCESS)
	{
		return -1L;
	}

	if (m_ppsInfo[lIndex].m_Process_Information.hProcess != NULL)
	{
		if (GetExitCodeProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,
			&dwExitCode))
		{
			if (dwExitCode == STILL_ACTIVE) 
			{
				TerminateProcess(m_ppsInfo[lIndex].m_Process_Information.hProcess,-1);
			}
		}
		CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hProcess);
		m_ppsInfo[lIndex].m_Process_Information.hProcess = NULL;
	}

	if (m_ppsInfo[lIndex].m_Process_Information.hThread != NULL)
	{
		if (GetExitCodeThread(m_ppsInfo[lIndex].m_Process_Information.hThread,
			&dwExitCode))
		{
			if (dwExitCode == STILL_ACTIVE) 
			{
				TerminateThread(m_ppsInfo[lIndex].m_Process_Information.hThread,-1);
			}
		}

		CloseHandle(m_ppsInfo[lIndex].m_Process_Information.hThread);
		m_ppsInfo[lIndex].m_Process_Information.hThread = NULL;
	}	
	return 0L;
}

LONG CProcessHandle::KillAllProcess()
{
	for (int rii = 0; rii < MAX_SUPPORT_PROCESS; rii++)
	{
		KillOneProcessByIndex(rii);
	}
	return 0L;
}
CProcessHandle& CProcessHandle::Instance(void)
{
	static CProcessHandle instance;
	return instance;
}